home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / amitcp / netinet / tcp_output.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  16.8 KB  |  578 lines

  1. RCS_ID_C="$Id: tcp_output.c,v 1.9 1993/06/04 11:16:15 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * HISTORY
  8.  * $Log: tcp_output.c,v $
  9.  * Revision 1.9  1993/06/04  11:16:15  jraja
  10.  * Fixes for first public release.
  11.  *
  12.  * Revision 1.8  1993/05/17  00:16:44  ppessi
  13.  * Changed RCS version. Added rcsid.
  14.  *
  15.  * Revision 1.7  1993/04/24  23:22:13  jraja
  16.  * Removed #ifdef NOALIGN, now using straight structure copies.
  17.  *
  18.  * Revision 1.6  93/04/13  22:16:32  22:16:32  jraja (Jarno Tapio Rajahalme)
  19.  * Added ALIGNED to the tcp_initopt (which was odd aligned).
  20.  * 
  21.  * Revision 1.5  93/04/05  19:06:32  19:06:32  jraja (Jarno Tapio Rajahalme)
  22.  * Changed storage of the spl functions  return values to type spl_t.
  23.  * Added include for conf.h to every .c file.
  24.  * 
  25.  * Revision 1.4  93/03/22  16:59:39  16:59:39  jraja (Jarno Tapio Rajahalme)
  26.  * Changed bcopy()s and bzero()s with word aligned pointers to
  27.  * aligned_b(copy|zero) ar aligned_b(copy|zero)_const. The latter is for calls
  28.  * in which the size is constant.
  29.  * These can be disabled by defining NOALIGN.
  30.  *  Converted bcopys doing structure copies (on aligned pointers) to structure
  31.  * assignments, since at least SASC produces better code with assignment.
  32.  * 
  33.  * Revision 1.3  93/03/03  21:29:37  21:29:37  jraja (Jarno Tapio Rajahalme)
  34.  * Moved various data definitions from header files to here.
  35.  * 
  36.  * Revision 1.2  93/02/26  09:49:02  09:49:02  jraja (Jarno Tapio Rajahalme)
  37.  * Made this compile with ANSI C (added prototypes).
  38.  * Added one (phony) argument to tcp_quench() call, since it now takes two
  39.  * arguments, but does not use the second.
  40.  * 
  41.  * Revision 1.1  92/11/17  16:30:39  16:30:39  jraja (Jarno Tapio Rajahalme)
  42.  * Initial revision
  43.  *
  44.  */
  45.  
  46. /*
  47.  * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
  48.  * All rights reserved.
  49.  *
  50.  * Redistribution and use in source and binary forms, with or without
  51.  * modification, are permitted provided that the following conditions
  52.  * are met:
  53.  * 1. Redistributions of source code must retain the above copyright
  54.  *    notice, this list of conditions and the following disclaimer.
  55.  * 2. Redistributions in binary form must reproduce the above copyright
  56.  *    notice, this list of conditions and the following disclaimer in the
  57.  *    documentation and/or other materials provided with the distribution.
  58.  * 3. All advertising materials mentioning features or use of this software
  59.  *    must display the following acknowledgement:
  60.  *    This product includes software developed by the University of
  61.  *    California, Berkeley and its contributors.
  62.  * 4. Neither the name of the University nor the names of its contributors
  63.  *    may be used to endorse or promote products derived from this software
  64.  *    without specific prior written permission.
  65.  *
  66.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  67.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  68.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  69.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  70.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  71.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  72.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  73.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  74.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  75.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  76.  * SUCH DAMAGE.
  77.  *
  78.  *    @(#)tcp_output.c    7.22 (Berkeley) 8/31/90
  79.  */
  80.  
  81. #include <conf.h>
  82.  
  83. #include <sys/param.h>
  84. #include <sys/systm.h>
  85. #include <sys/malloc.h>
  86. #include <sys/mbuf.h>
  87. #include <sys/protosw.h>
  88. #include <sys/socket.h>
  89. #include <sys/socketvar.h>
  90. #include <sys/errno.h>
  91. #include <sys/synch.h>
  92.  
  93. #include <net/route.h>
  94.  
  95. #include <netinet/in.h>
  96. #include <netinet/in_systm.h>
  97. #include <netinet/ip.h>
  98. #include <netinet/in_pcb.h>
  99. #include <netinet/ip_var.h>
  100. #include <netinet/tcp.h>
  101. #define    TCPOUTFLAGS
  102. #include <netinet/tcp_fsm.h>
  103. #include <netinet/tcp_seq.h>
  104. #include <netinet/tcp_timer.h>
  105. #include <netinet/tcp_var.h>
  106. #include <netinet/tcpip.h>
  107. #include <netinet/tcp_debug.h>
  108.  
  109. #include <netinet/tcp_output_protos.h>
  110. #include <netinet/tcp_input_protos.h>
  111. #include <netinet/tcp_debug_protos.h>
  112. #include <netinet/tcp_subr_protos.h>
  113. #include <netinet/ip_output_protos.h>
  114. #include <netinet/in_cksum_protos.h>
  115.  
  116. #ifdef notyet
  117. extern struct mbuf *m_copypack();
  118. #endif
  119.  
  120. /* --- start moved from tcp_fsm.h --- */
  121. #ifdef    TCPOUTFLAGS
  122. /*
  123.  * Flags used when sending segments in tcp_output.
  124.  * Basic flags (TH_RST,TH_ACK,TH_SYN,TH_FIN) are totally
  125.  * determined by state, with the proviso that TH_FIN is sent only
  126.  * if all data queued for output is included in the segment.
  127.  */
  128. u_char    tcp_outflags[TCP_NSTATES] = {
  129.     TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
  130.     TH_ACK, TH_ACK,
  131.     TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK,
  132. };
  133. #endif
  134. /* --- end moved from tcp_fsm.h --- */
  135.  
  136. /*
  137.  * Initial options.
  138.  */
  139. ALIGNED u_char    tcp_initopt[4] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, };
  140.  
  141. /*
  142.  * Tcp output routine: figure out what should be sent and send it.
  143.  */
  144. int
  145. tcp_output(tp)
  146.     register struct tcpcb *tp;
  147. {
  148.     register struct socket *so = tp->t_inpcb->inp_socket;
  149.     register long len, win;
  150.     int off, flags, error;
  151.     register struct mbuf *m;
  152.     register struct tcpiphdr *ti;
  153.     u_char *opt;
  154.     unsigned optlen, hdrlen;
  155.     int idle, sendalot;
  156.  
  157.     /*
  158.      * Determine length of data that should be transmitted,
  159.      * and flags that will be used.
  160.      * If there is some data or critical controls (SYN, RST)
  161.      * to send, then transmit; otherwise, investigate further.
  162.      */
  163.     idle = (tp->snd_max == tp->snd_una);
  164.     if (idle && tp->t_idle >= tp->t_rxtcur)
  165.         /*
  166.          * We have been idle for "a while" and no acks are
  167.          * expected to clock out any data we send --
  168.          * slow start to get ack "clock" running again.
  169.          */
  170.         tp->snd_cwnd = tp->t_maxseg;
  171. again:
  172.     sendalot = 0;
  173.     off = tp->snd_nxt - tp->snd_una;
  174.     win = min(tp->snd_wnd, tp->snd_cwnd);
  175.  
  176.     /*
  177.      * If in persist timeout with window of 0, send 1 byte.
  178.      * Otherwise, if window is small but nonzero
  179.      * and timer expired, we will send what we can
  180.      * and go to transmit state.
  181.      */
  182.     if (tp->t_force) {
  183.         if (win == 0)
  184.             win = 1;
  185.         else {
  186.             tp->t_timer[TCPT_PERSIST] = 0;
  187.             tp->t_rxtshift = 0;
  188.         }
  189.     }
  190.  
  191.     flags = tcp_outflags[tp->t_state];
  192.     len = min(so->so_snd.sb_cc, win) - off;
  193.  
  194.     if (len < 0) {
  195.         /*
  196.          * If FIN has been sent but not acked,
  197.          * but we haven't been called to retransmit,
  198.          * len will be -1.  Otherwise, window shrank
  199.          * after we sent into it.  If window shrank to 0,
  200.          * cancel pending retransmit and pull snd_nxt
  201.          * back to (closed) window.  We will enter persist
  202.          * state below.  If the window didn't close completely,
  203.          * just wait for an ACK.
  204.          */
  205.         len = 0;
  206.         if (win == 0) {
  207.             tp->t_timer[TCPT_REXMT] = 0;
  208.             tp->snd_nxt = tp->snd_una;
  209.         }
  210.     }
  211.     if (len > tp->t_maxseg) {
  212.         len = tp->t_maxseg;
  213.         sendalot = 1;
  214.     }
  215.     if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
  216.         flags &= ~TH_FIN;
  217.  
  218.     win = sbspace(&so->so_rcv);
  219.  
  220.     /*
  221.      * Sender silly window avoidance.  If connection is idle
  222.      * and can send all data, a maximum segment,
  223.      * at least a maximum default-size segment do it,
  224.      * or are forced, do it; otherwise don't bother.
  225.      * If peer's buffer is tiny, then send
  226.      * when window is at least half open.
  227.      * If retransmitting (possibly after persist timer forced us
  228.      * to send into a small window), then must resend.
  229.      */
  230.     if (len) {
  231.         if (len == tp->t_maxseg)
  232.             goto send;
  233.         if ((idle || tp->t_flags & TF_NODELAY) &&
  234.             len + off >= so->so_snd.sb_cc)
  235.             goto send;
  236.         if (tp->t_force)
  237.             goto send;
  238.         if (len >= tp->max_sndwnd / 2)
  239.             goto send;
  240.         if (SEQ_LT(tp->snd_nxt, tp->snd_max))
  241.             goto send;
  242.     }
  243.  
  244.     /*
  245.      * Compare available window to amount of window
  246.      * known to peer (as advertised window less
  247.      * next expected input).  If the difference is at least two
  248.      * max size segments, or at least 50% of the maximum possible
  249.      * window, then want to send a window update to peer.
  250.      */
  251.     if (win > 0) {
  252.         long adv = win - (tp->rcv_adv - tp->rcv_nxt);
  253.  
  254.         if (adv >= (long) (2 * tp->t_maxseg))
  255.             goto send;
  256.         if (2 * adv >= (long) so->so_rcv.sb_hiwat)
  257.             goto send;
  258.     }
  259.  
  260.     /*
  261.      * Send if we owe peer an ACK.
  262.      */
  263.     if (tp->t_flags & TF_ACKNOW)
  264.         goto send;
  265.     if (flags & (TH_SYN|TH_RST))
  266.         goto send;
  267.     if (SEQ_GT(tp->snd_up, tp->snd_una))
  268.         goto send;
  269.     /*
  270.      * If our state indicates that FIN should be sent
  271.      * and we have not yet done so, or we're retransmitting the FIN,
  272.      * then we need to send.
  273.      */
  274.     if (flags & TH_FIN &&
  275.         ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
  276.         goto send;
  277.  
  278.     /*
  279.      * TCP window updates are not reliable, rather a polling protocol
  280.      * using ``persist'' packets is used to insure receipt of window
  281.      * updates.  The three ``states'' for the output side are:
  282.      *    idle            not doing retransmits or persists
  283.      *    persisting        to move a small or zero window
  284.      *    (re)transmitting    and thereby not persisting
  285.      *
  286.      * tp->t_timer[TCPT_PERSIST]
  287.      *    is set when we are in persist state.
  288.      * tp->t_force
  289.      *    is set when we are called to send a persist packet.
  290.      * tp->t_timer[TCPT_REXMT]
  291.      *    is set when we are retransmitting
  292.      * The output side is idle when both timers are zero.
  293.      *
  294.      * If send window is too small, there is data to transmit, and no
  295.      * retransmit or persist is pending, then go to persist state.
  296.      * If nothing happens soon, send when timer expires:
  297.      * if window is nonzero, transmit what we can,
  298.      * otherwise force out a byte.
  299.      */
  300.     if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&
  301.         tp->t_timer[TCPT_PERSIST] == 0) {
  302.         tp->t_rxtshift = 0;
  303.         tcp_setpersist(tp);
  304.     }
  305.  
  306.     /*
  307.      * No reason to send a segment, just return.
  308.      */
  309.     return (0);
  310.  
  311. send:
  312.     /*
  313.      * Before ESTABLISHED, force sending of initial options
  314.      * unless TCP set not to do any options.
  315.      * NOTE: we assume that the IP/TCP header plus TCP options
  316.      * always fit in a single mbuf, leaving room for a maximum
  317.      * link header, i.e.
  318.      *    max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
  319.      */
  320.     optlen = 0;
  321.     hdrlen = sizeof (struct tcpiphdr);
  322.     if (flags & TH_SYN && (tp->t_flags & TF_NOOPT) == 0) {
  323.         opt = tcp_initopt;
  324.         optlen = sizeof (tcp_initopt);
  325.         hdrlen += sizeof (tcp_initopt);
  326.         *(u_short *)(opt + 2) = htons((u_short) tcp_mss(tp, 0));
  327. #if DIAGNOSTIC
  328.          if (max_linkhdr + hdrlen > MHLEN)
  329.             panic("tcphdr too big");
  330. #endif
  331.     }
  332.  
  333.     /*
  334.      * Grab a header mbuf, attaching a copy of data to
  335.      * be transmitted, and initialize the header from
  336.      * the template for sends on this connection.
  337.      */
  338.     if (len) {
  339.         if (tp->t_force && len == 1)
  340.             tcpstat.tcps_sndprobe++;
  341.         else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
  342.             tcpstat.tcps_sndrexmitpack++;
  343.             tcpstat.tcps_sndrexmitbyte += len;
  344.         } else {
  345.             tcpstat.tcps_sndpack++;
  346.             tcpstat.tcps_sndbyte += len;
  347.         }
  348. #ifdef notyet
  349.         if ((m = m_copypack(so->so_snd.sb_mb, off,
  350.             (int)len, max_linkhdr + hdrlen)) == 0) {
  351.             error = ENOBUFS;
  352.             goto out;
  353.         }
  354.         /*
  355.          * m_copypack left space for our hdr; use it.
  356.          */
  357.         m->m_len += hdrlen;
  358.         m->m_data -= hdrlen;
  359. #else
  360.         MGETHDR(m, M_DONTWAIT, MT_HEADER);
  361.         if (m == NULL) {
  362.             error = ENOBUFS;
  363.             goto out;
  364.         }
  365.         m->m_data += max_linkhdr;
  366.         m->m_len = hdrlen;
  367.         if (len <= MHLEN - hdrlen - max_linkhdr) {
  368.             m_copydata(so->so_snd.sb_mb, off, (int) len,
  369.                 mtod(m, caddr_t) + hdrlen);
  370.             m->m_len += len;
  371.         } else {
  372.             m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
  373.             if (m->m_next == 0)
  374.                 len = 0;
  375.         }
  376. #endif
  377.         /*
  378.          * If we're sending everything we've got, set PUSH.
  379.          * (This will keep happy those implementations which only
  380.          * give data to the user when a buffer fills or
  381.          * a PUSH comes in.)
  382.          */
  383.         if (off + len == so->so_snd.sb_cc)
  384.             flags |= TH_PUSH;
  385.     } else {
  386.         if (tp->t_flags & TF_ACKNOW)
  387.             tcpstat.tcps_sndacks++;
  388.         else if (flags & (TH_SYN|TH_FIN|TH_RST))
  389.             tcpstat.tcps_sndctrl++;
  390.         else if (SEQ_GT(tp->snd_up, tp->snd_una))
  391.             tcpstat.tcps_sndurg++;
  392.         else
  393.             tcpstat.tcps_sndwinup++;
  394.  
  395.         MGETHDR(m, M_DONTWAIT, MT_HEADER);
  396.         if (m == NULL) {
  397.             error = ENOBUFS;
  398.             goto out;
  399.         }
  400.         m->m_data += max_linkhdr;
  401.         m->m_len = hdrlen;
  402.     }
  403.     m->m_pkthdr.rcvif = (struct ifnet *)0;
  404.     ti = mtod(m, struct tcpiphdr *);
  405.     if (tp->t_template == 0)
  406.         panic("tcp_output");
  407.     *ti = *tp->t_template;
  408.     /*
  409.      * Fill in fields, remembering maximum advertised
  410.      * window for use in delaying messages about window sizes.
  411.      * If resending a FIN, be sure not to use a new sequence number.
  412.      */
  413.     if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && 
  414.         tp->snd_nxt == tp->snd_max)
  415.         tp->snd_nxt--;
  416.     ti->ti_seq = htonl(tp->snd_nxt);
  417.     ti->ti_ack = htonl(tp->rcv_nxt);
  418.     if (optlen) {
  419.         aligned_bcopy((caddr_t)opt, (caddr_t)(ti + 1), optlen);
  420.         ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
  421.     }
  422.     ti->ti_flags = flags;
  423.     /*
  424.      * Calculate receive window.  Don't shrink window,
  425.      * but avoid silly window syndrome.
  426.      */
  427.     if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg)
  428.         win = 0;
  429.     if (win > TCP_MAXWIN)
  430.         win = TCP_MAXWIN;
  431.     if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
  432.         win = (long)(tp->rcv_adv - tp->rcv_nxt);
  433.     ti->ti_win = htons((u_short)win);
  434.     if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
  435.         ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
  436.         ti->ti_flags |= TH_URG;
  437.     } else
  438.         /*
  439.          * If no urgent pointer to send, then we pull
  440.          * the urgent pointer to the left edge of the send window
  441.          * so that it doesn't drift into the send window on sequence
  442.          * number wraparound.
  443.          */
  444.         tp->snd_up = tp->snd_una;        /* drag it along */
  445.  
  446.     /*
  447.      * Put TCP length in extended header, and then
  448.      * checksum extended header and data.
  449.      */
  450.     if (len + optlen)
  451.         ti->ti_len = htons((u_short)(sizeof (struct tcphdr) +
  452.             optlen + len));
  453.     ti->ti_sum = in_cksum(m, (int)(hdrlen + len));
  454.  
  455.     /*
  456.      * In transmit state, time the transmission and arrange for
  457.      * the retransmit.  In persist state, just set snd_max.
  458.      */
  459.     if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
  460.         tcp_seq startseq = tp->snd_nxt;
  461.  
  462.         /*
  463.          * Advance snd_nxt over sequence space of this segment.
  464.          */
  465.         if (flags & (TH_SYN|TH_FIN)) {
  466.             if (flags & TH_SYN)
  467.                 tp->snd_nxt++;
  468.             if (flags & TH_FIN) {
  469.                 tp->snd_nxt++;
  470.                 tp->t_flags |= TF_SENTFIN;
  471.             }
  472.         }
  473.         tp->snd_nxt += len;
  474.         if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
  475.             tp->snd_max = tp->snd_nxt;
  476.             /*
  477.              * Time this transmission if not a retransmission and
  478.              * not currently timing anything.
  479.              */
  480.             if (tp->t_rtt == 0) {
  481.                 tp->t_rtt = 1;
  482.                 tp->t_rtseq = startseq;
  483.                 tcpstat.tcps_segstimed++;
  484.             }
  485.         }
  486.  
  487.         /*
  488.          * Set retransmit timer if not currently set,
  489.          * and not doing an ack or a keep-alive probe.
  490.          * Initial value for retransmit timer is smoothed
  491.          * round-trip time + 2 * round-trip time variance.
  492.          * Initialize shift counter which is used for backoff
  493.          * of retransmit time.
  494.          */
  495.         if (tp->t_timer[TCPT_REXMT] == 0 &&
  496.             tp->snd_nxt != tp->snd_una) {
  497.             tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
  498.             if (tp->t_timer[TCPT_PERSIST]) {
  499.                 tp->t_timer[TCPT_PERSIST] = 0;
  500.                 tp->t_rxtshift = 0;
  501.             }
  502.         }
  503.     } else
  504.         if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
  505.             tp->snd_max = tp->snd_nxt + len;
  506.  
  507.     /*
  508.      * Trace.
  509.      */
  510.     if (so->so_options & SO_DEBUG)
  511.         tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0);
  512.  
  513.     /*
  514.      * Fill in IP length and desired time to live and
  515.      * send to IP level.  There should be a better way
  516.      * to handle ttl and tos; we could keep them in
  517.      * the template, but need a way to checksum without them.
  518.      */
  519.     m->m_pkthdr.len = hdrlen + len;
  520.     ((struct ip *)ti)->ip_len = m->m_pkthdr.len;
  521.     ((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl;    /* XXX */
  522.     ((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip.ip_tos;    /* XXX */
  523. #if BSD >= 43
  524.     error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
  525.         so->so_options & SO_DONTROUTE);
  526. #else
  527.     error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, 
  528.         so->so_options & SO_DONTROUTE);
  529. #endif
  530.     if (error) {
  531. out:
  532.         if (error == ENOBUFS) {
  533.             tcp_quench(tp->t_inpcb, 0);
  534.             return (0);
  535.         }
  536.         if ((error == EHOSTUNREACH || error == ENETDOWN)
  537.             && TCPS_HAVERCVDSYN(tp->t_state)) {
  538.             tp->t_softerror = error;
  539.             return (0);
  540.         }
  541.         return (error);
  542.     }
  543.     tcpstat.tcps_sndtotal++;
  544.  
  545.     /*
  546.      * Data sent (as far as we can tell).
  547.      * If this advertises a larger window than any other segment,
  548.      * then remember the size of the advertised window.
  549.      * Any pending ACK has now been sent.
  550.      */
  551.     if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
  552.         tp->rcv_adv = tp->rcv_nxt + win;
  553.     tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
  554.     if (sendalot)
  555.         goto again;
  556.     return (0);
  557. }
  558.  
  559. void
  560. tcp_setpersist(tp)
  561.     register struct tcpcb *tp;
  562. {
  563.     register t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
  564.  
  565.     if (tp->t_timer[TCPT_REXMT])
  566.         panic("tcp_output REXMT");
  567.     /*
  568.      * Start/restart persistance timer.
  569.      */
  570.     TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
  571.         t * tcp_backoff[tp->t_rxtshift],
  572.         TCPTV_PERSMIN, TCPTV_PERSMAX);
  573.     if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
  574.         tp->t_rxtshift++;
  575. }
  576.  
  577.  
  578.